/*
 * Dcm_UDS0x27.c
 *
 *  Created on: 2018-1-16
 *      Author: Shute
 */
#include "UDS.h"



/****************************************************************
	 UDS:SecurityAccess(27 hex) service
 ***************************************************************/
#if(STD_ON == DCM_UDS_SERVICE0X27_ENABLED)

static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceConditionCheck(
        uint8 ProtocolCtrlId);


static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceSubfunctionCheck(
        uint8 ProtocolCtrlId,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)MsgCtrlID,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)ReqSecLevel,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)SecCfgIndex,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)SubFunction);


static FUNC(void, DCM_CODE)Dcm_Uds0x27ServiceReqSeedResp(
        uint8   ProtocolCtrlId,
        uint8   MsgCtrlID,
        uint8   SubFunction,
        uint16  Offset,
        uint8   SeedSize,
        Std_ReturnType ret);

static FUNC(void, DCM_CODE)Dcm_Uds0x27ServiceCompareKeyResp(
            Dcm_OpStatusType OpStatus,
			uint8 	 ProtocolCtrlId,
			uint8    MsgCtrlID,
			uint8    SubFunction,
			uint16   Offset,
			uint8    ReqSecLevel,
			uint8    SecCfgIndex,
			Std_ReturnType ret);

static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceActiveSecLevelCheck(
				uint8   ProtocolCtrlId,
				uint8   MsgCtrlID,
				uint8   ReqSecLevel,
				uint16  Offset,
				uint8   SeedSize,
				uint8   SubFunction);


static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceStatusCheck(
            Dcm_OpStatusType OpStatus,
			uint8 ProtocolCtrlId,
			uint8 SubFunction,
            uint8 SecCfgIndex);


static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceMsgLenCheck(
        Dcm_OpStatusType OpStatus,
        uint8  ProtocolCtrlId,
        uint8  SubFunction,
        uint8  ReqLen,
        uint8  AdrSize,
        uint8  KeySize,
        uint8 SecCfgIndex);
		
/*******************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceConditionCheck(
        uint8 ProtocolCtrlId)
{
	Std_ReturnType ret;

	/*************************************************/
	#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
	/*session check,check whether the current
	 * session supports the request service*/
	ret = DsdInternal_SesCheck(ProtocolCtrlId, SID_SECURITY_ACCESS);
	if(E_NOT_OK == ret)
	{
		/****@req DCM-FUNR-073[DCM211]****/
		/*the current session does not support
		 *  the request service,send NRC = 0x7F*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,
		        DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	#endif

    /*************************************************/
	#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
	/*security check,check whether the current
	 *  security supports the request service*/
	ret = DsdInternal_SecurityCheck(ProtocolCtrlId,
	        SID_SECURITY_ACCESS);
	if(E_NOT_OK == ret)
	{
		/****@req DCM-FUNR-074[DCM217]****/
		/*the current security does not support
		 * the request service,send NRC = 0x33*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,
		        DCM_E_SECURITYACCESSDENIED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	#endif

	return E_OK;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

/********************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceSubfunctionCheck(
        uint8 ProtocolCtrlId,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)MsgCtrlID,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)ReqSecLevel,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)SecCfgIndex,
        P2VAR(uint8, AUTOMATIC, AUTOMATIC)SubFunction)
{
	Std_ReturnType ret;

	/********************************/
	/*try to find the corresponding security level in configuration*/
	*MsgCtrlID   = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
	*SubFunction = Dcm_MsgCtrl[*MsgCtrlID].Subfunction;
	*ReqSecLevel = (*SubFunction + 1u)/2u;
	/*********************************************/
	if(*ReqSecLevel == 0x00u)
	{
	    /*if not found in DcmDspSecurityRow,send NRC 0x12*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_NOT_OK;

	}
	/*********************************************/
	ret = DslInternal_GetSecurityCfgBySecLevel(*ReqSecLevel, SecCfgIndex);
	if(E_NOT_OK == ret)
	{
		/*SWS_Dcm_00321*/
		/*if not found in DcmDspSecurityRow,send NRC 0x12*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
	}

	return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif
/********************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(void, DCM_CODE)Dcm_Uds0x27ServiceReqSeedResp(
        uint8   ProtocolCtrlId,
        uint8   MsgCtrlID,
        uint8   SubFunction,
        uint16  Offset,
        uint8   SeedSize,
        Std_ReturnType ret)
{
	switch(ret)
	{
		case E_OK:
			SchM_Enter_Dcm(Dcm_MsgCtrl);
			Dcm_Channel[Offset] = 0x67;
			Dcm_Channel[Offset + 1u] = SubFunction;
			Dcm_MsgCtrl[MsgCtrlID].MsgContext.ResMaxDataLen =((uint32)SeedSize+2UL);
			Dcm_MsgCtrl[MsgCtrlID].MsgContext.ResDataLen    =((uint32)SeedSize+2UL);
			Dcm_MsgCtrl[MsgCtrlID].MsgContext.pResData      =&Dcm_Channel[Offset];
			SchM_Exit_Dcm(Dcm_MsgCtrl);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			SchM_Enter_Dcm(Dcm_SecCtrl);
			/*seed has been sent,set the status to DCM_SERVICE_SEED*/
			Dcm_SecCtrl.Dcm_SecServiceState = DCM_SERVICE_SEED;
			Dcm_SecCtrl.Dcm_SubfunctionForSeed = SubFunction;
			SchM_Exit_Dcm(Dcm_SecCtrl);
			break;

		case E_NOT_OK:
			/*if fail to get seed,send NRC 0x22*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;

		case DCM_E_PENDING:
			Dcm_MsgCtrl[MsgCtrlID].Dcm_OpStatus = DCM_PENDING;
			break;

		case DCM_E_EXCEEDEDNUMBEROFATTEMPTS:/*Momus JJE Speci*/
            DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_EXCEEDEDNUMBEROFATTEMPTS);/*NRC=0x36*/
            DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;

		default:
			/*unexpected return value,send NRC 0x22*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;
	}

}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(void, DCM_CODE)Dcm_Uds0x27ServiceCompareKeyResp(
            Dcm_OpStatusType OpStatus,
			uint8 	 ProtocolCtrlId,
			uint8    MsgCtrlID,
			uint8    SubFunction,
			uint16   Offset,
			uint8    ReqSecLevel,
			uint8    SecCfgIndex,
			Std_ReturnType ret)
{
    P2CONST(Dcm_DspSecurityRowType,AUTOMATIC,DCM_CONST)pSecurityRow;

	switch(ret)
	{
		case E_OK:
			Dcm_Channel[Offset] = 0x67;
			Dcm_Channel[Offset + 1u] = SubFunction;
			Dcm_MsgCtrl[MsgCtrlID].MsgContext.ResMaxDataLen = 2UL;
			Dcm_MsgCtrl[MsgCtrlID].MsgContext.ResDataLen    = 2UL;
			Dcm_MsgCtrl[MsgCtrlID].MsgContext.pResData      = &Dcm_Channel[Offset];
			SchM_Enter_Dcm(Dcm_SecCtrl);
			Dcm_SecCtrl.Dcm_NewSec = ReqSecLevel;
			Dcm_SecCtrl.Dcm_SecServiceState = DCM_SERVICE_KEY;
			SchM_Exit_Dcm(Dcm_SecCtrl);
			DsdInternal_ProcessingDone(ProtocolCtrlId);

            SchM_Enter_Dcm(Dcm_SecCtrl);
            Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex] = 0u;
            Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecTimerState[SecCfgIndex]   = DCM_SECTIMER_OFF;
            SchM_Exit_Dcm(Dcm_SecCtrl);
            pSecurityRow = &(Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex]);
            if (pSecurityRow != NULL_PTR)
            {
                /*SWS_Dcm_01157*/
                if ((TRUE == pSecurityRow->DcmDspSecurityAttemptCounterEnabled)
                   &&((USE_ASYNCH_FNC == pSecurityRow->DcmDspSecurityUsePort)
                   || (USE_ASYNCH_CLIENT_SERVER == pSecurityRow->DcmDspSecurityUsePort)))
                {
                    if (pSecurityRow->Dcm_SetSecurityAttemptCounterFnc != NULL_PTR)
                    {
                        /*SWS_Dcm_01154*/
                        ret = pSecurityRow->Dcm_SetSecurityAttemptCounterFnc(OpStatus,
                                Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]);
                        if (DCM_E_PENDING == ret)
                        {
                            /*idle*/
                        }
                    }
                }
            }
			break;

		case E_NOT_OK:
			/*ret = E_NOT_OK,sent NRC 0x22*/
			DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
			(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;

		case DCM_E_PENDING:
			Dcm_MsgCtrl[MsgCtrlID].Dcm_OpStatus = DCM_PENDING;
			break;

		case E_COMPARE_KEY_FAILED:
			/*'compare key' is failed,increase the false count*/
			SchM_Enter_Dcm(Dcm_SecCtrl);
			Dcm_SecCtrl.Dcm_SubfunctionForSeed = 0u;
			Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex] += (uint8)1;
            SchM_Exit_Dcm(Dcm_SecCtrl);
			pSecurityRow = &(Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex]);
            if (pSecurityRow != NULL_PTR)
            {
                /*SWS_Dcm_01157*/
                if ((TRUE == pSecurityRow->DcmDspSecurityAttemptCounterEnabled)
                   &&((USE_ASYNCH_FNC == pSecurityRow->DcmDspSecurityUsePort)
                           || (USE_ASYNCH_CLIENT_SERVER == pSecurityRow->DcmDspSecurityUsePort)))
                {
                    if (pSecurityRow->Dcm_SetSecurityAttemptCounterFnc != NULL_PTR)
                    {
                        /*SWS_Dcm_01154*/
                        ret = pSecurityRow->Dcm_SetSecurityAttemptCounterFnc(OpStatus,
                                Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]);
                        if (DCM_E_PENDING == ret)
                        {
                            /*idle*/
                        }
                    }
                }
                if(Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]
                                     >= pSecurityRow->DcmDspSecurityNumAttDelay)
                {
                    SchM_Enter_Dcm(Dcm_SecCtrl);
                    Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecCurTimer[SecCfgIndex]     = Frt_ReadOutMS();
                    Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecExpiredTimer[SecCfgIndex] =
                    (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityDelayTime;
                    Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecTimerState[SecCfgIndex]   = DCM_SECTIMER_ON;
                    SchM_Exit_Dcm(Dcm_SecCtrl);

                    DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
                    (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_EXCEEDEDNUMBEROFATTEMPTS);/*NRC=0x36*/
                    DsdInternal_ProcessingDone(ProtocolCtrlId);
                }
                else
                {
                    DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
                    (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_INVALIDKEY);/*NRC=0x35*/
                    DsdInternal_ProcessingDone(ProtocolCtrlId);
                }
            }
            else
            {
                /*send NRC 0x22*/
                DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
                (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
                DsdInternal_ProcessingDone(ProtocolCtrlId);
            }
			break;
		default:
			/*unexpected return value is present,send NRC 0x22*/
			DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
			(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;
	}

}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceActiveSecLevelCheck(
				uint8   ProtocolCtrlId,
				uint8   MsgCtrlID,
				uint8   ReqSecLevel,
				uint16  Offset,
				uint8   SeedSize,
				uint8   SubFunction)
{
	uint8       Index;
	Std_ReturnType ret = E_OK;

	if (ReqSecLevel == Dcm_SecCtrl.Dcm_ActiveSec)
	{
		/*SWS_Dcm_00323*/
		/*if the server is on the request security level,set seed to zero*/
		SchM_Enter_Dcm(Dcm_MsgCtrl);
		Dcm_Channel[Offset] = 0x67;
		Dcm_Channel[Offset + 1u] = SubFunction;
		for (Index = 0; Index < SeedSize; Index++)
		{
			Dcm_Channel[Offset + (uint16)Index+ 2u] = 0x00u;
		}
		Dcm_MsgCtrl[MsgCtrlID].MsgContext.ResMaxDataLen = ((uint32)SeedSize + 2u);
		Dcm_MsgCtrl[MsgCtrlID].MsgContext.ResDataLen    = ((uint32)SeedSize + 2u);
		Dcm_MsgCtrl[MsgCtrlID].MsgContext.pResData      = &Dcm_Channel[Offset];
		SchM_Exit_Dcm(Dcm_MsgCtrl);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceStatusCheck(
            Dcm_OpStatusType OpStatus,
			uint8 ProtocolCtrlId,
			uint8 SubFunction,
            uint8 SecCfgIndex)
{
	Std_ReturnType ret = E_OK;
	P2CONST(Dcm_DspSecurityRowType,AUTOMATIC,DCM_CONST)pSecurityRow;

	/*check the status*/
	if (DCM_SERVICE_SEED != Dcm_SecCtrl.Dcm_SecServiceState)
	{
		/*if the server is not on the status DCM_SERVICE_SEED,
		 * send NRC 0x24:request sequence error*/
		DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTSEQUENCEERROR);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_NOT_OK;
	}
	if ((SubFunction <= Dcm_SecCtrl.Dcm_SubfunctionForSeed)
		|| (1u != (SubFunction-(Dcm_SecCtrl.Dcm_SubfunctionForSeed))))
	{
		/*'requestSeed' and 'seedKey' don't  match*/
		SchM_Enter_Dcm(Dcm_SecCtrl);
		Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex] += (uint8)1;
		if(Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex] >=
		   Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex].DcmDspSecurityNumAttDelay)
		{
			Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecCurTimer[SecCfgIndex]     = Frt_ReadOutMS();
			Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecExpiredTimer[SecCfgIndex] =
			(Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityDelayTime;
			Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecTimerState[SecCfgIndex]   = DCM_SECTIMER_ON;
			SchM_Exit_Dcm(Dcm_SecCtrl);
		}
        pSecurityRow = &(Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex]);
        if (pSecurityRow != NULL_PTR)
        {
            /*SWS_Dcm_01157*/
            if ((TRUE == pSecurityRow->DcmDspSecurityAttemptCounterEnabled)
               &&((USE_ASYNCH_FNC == pSecurityRow->DcmDspSecurityUsePort)
                       || (USE_ASYNCH_CLIENT_SERVER == pSecurityRow->DcmDspSecurityUsePort)))
            {
                if (pSecurityRow->Dcm_SetSecurityAttemptCounterFnc != NULL_PTR)
                {
                    /*SWS_Dcm_01154*/
                    ret = pSecurityRow->Dcm_SetSecurityAttemptCounterFnc(OpStatus,
                            Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]);
                    if (DCM_E_PENDING == ret)
                    {
                        /*idle*/
                    }
                }
            }
        }

		DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_NOT_OK;
	}
	return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x27ServiceMsgLenCheck(
        Dcm_OpStatusType OpStatus,
        uint8  ProtocolCtrlId,
        uint8  SubFunction,
        uint8  ReqLen,
        uint8  AdrSize,
        uint8  KeySize,
        uint8 SecCfgIndex)
{
	uint8  ReqCfgLen;
	Std_ReturnType ret = E_OK;
    P2CONST(Dcm_DspSecurityRowType,AUTOMATIC,DCM_CONST)pSecurityRow;

	if (1u == (SubFunction & 0x01u))
	{
		ReqCfgLen = (uint8)(AdrSize + 2u);
	}
	else
	{
		ReqCfgLen = (uint8)(KeySize + 2u);
	}
	if (ReqLen != ReqCfgLen)
	{
		/*if the request message length is not correct,send NRC 0x13*/
	    /*deal with 'request seed'*/
	    if (0x01u != (SubFunction & 0x01u))
	    {
	    	SchM_Enter_Dcm(Dcm_SecCtrl);
            Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex] += (uint8)1;
        	if(Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]
        	   >= Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex].
        	   DcmDspSecurityNumAttDelay)
        	{
        		Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecCurTimer[SecCfgIndex]     = Frt_ReadOutMS();
        		Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecExpiredTimer[SecCfgIndex] =
        		(Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityDelayTime;
        		Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecTimerState[SecCfgIndex]   = DCM_SECTIMER_ON;
        	}
            pSecurityRow = &(Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex]);
            if (pSecurityRow != NULL_PTR)
            {
                /*SWS_Dcm_01157*/
                if ((TRUE == pSecurityRow->DcmDspSecurityAttemptCounterEnabled)
                   &&((USE_ASYNCH_FNC == pSecurityRow->DcmDspSecurityUsePort)
                           || (USE_ASYNCH_CLIENT_SERVER == pSecurityRow->DcmDspSecurityUsePort)))
                {
                    if (pSecurityRow->Dcm_SetSecurityAttemptCounterFnc != NULL_PTR)
                    {
                        /*SWS_Dcm_01154*/
                        ret = pSecurityRow->Dcm_SetSecurityAttemptCounterFnc(OpStatus,
                                Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]);
                        if (DCM_E_PENDING == ret)
                        {
                            /*idle*/
                        }
                    }
                }
            }
	    }
		DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_NOT_OK;
	}
	return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif
uint8 Last_Seed[16] = {0};
/********************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x27(
		Dcm_OpStatusType OpStatus,
		uint8 ProtocolCtrlId,
		P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
	uint8       Index;
	uint8       ReqSecLevel;
	uint8       SubFunction;
	uint8       MsgCtrlID;
	uint8       SecCfgIndex = 0u;
	uint8       ReqLen;
	uint8       AdrSize;
	uint8       SeedSize;
	uint8       KeySize;
	uint8       TxChannelCtrlIndex;
	uint8       TxChannelCfgIndex;
	uint16      Offset;
#if(STD_ON == DCM_MINIMUMLENGTH_CHECK_ENABLED)
    uint8       MsgCtrlIndex;
    uint16      MsgLength;
#endif
	#if (DCM_SECURITY_ADR_MAXSIZE > 0)
	uint8   Dcm_Adr[DCM_SECURITY_ADR_MAXSIZE] = {0};
	#endif
	Dcm_CompareKeyFncType ComparedKey = NULL_PTR;
	Dcm_GetSeedFncType GottSeed = NULL_PTR;
#endif
	Std_ReturnType ret;
	P2CONST(Dcm_DspSecurityRowType,AUTOMATIC,DCM_CONST)pSecurityRow;

    /*************************************************/
    ret = Dcm_Uds0x27ServiceConditionCheck(ProtocolCtrlId);
    if(E_OK != ret)
    {
        return ret;
    }
	#if(STD_ON == DCM_MINIMUMLENGTH_CHECK_ENABLED)
    /*************************************************/
    MsgCtrlIndex =  Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
    MsgLength = (uint16)Dcm_MsgCtrl[MsgCtrlIndex].MsgContext.ReqDataLen;
    if(MsgLength < DCM_UDS0X27_REQ_DATA_MINLENGTH)
    {
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
    }
	#endif
	/*************************************************/
	ret = Dcm_Uds0x27ServiceSubfunctionCheck(	ProtocolCtrlId,
	                      						&MsgCtrlID,
	                      						&ReqSecLevel,
	                      						&SecCfgIndex,
	                      						&SubFunction);
	if(E_OK != ret)
	{
		return ret;
	}

    /*************************************************/
    #if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    /*session check,check whether the current session supports the request service*/
    ret = DsdInternal_SubSesCheck(ProtocolCtrlId, SID_SECURITY_ACCESS);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-073[DCM211]****/
        /*the current session does not support the request service,send NRC = 0x7F*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SUBFUNCTIONNOTSUPPORTEDINACTIVESESSION);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
    #endif

    /*************************************************/
    #if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    /*security check,check whether the current security supports the request service*/
    ret = DsdInternal_SubSecurityCheck(ProtocolCtrlId, SID_SECURITY_ACCESS);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-074[DCM217]****/
        /*the current security does not support the request service,send NRC = 0x33*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SECURITYACCESSDENIED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
    #endif

	/*************************************************/
#if(STD_OFF == DCM_SECURITY_FUNC_ENABLED)
	DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
	DsdInternal_ProcessingDone(ProtocolCtrlId);
	return  E_NOT_OK;
#else
	/*if the delay timer is active and a request is transmitted,send NRC 0x37*/
	if((DCM_SECTIMER_ON == Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecTimerState[SecCfgIndex])
	    && (Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]
	    >= Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex].DcmDspSecurityNumAttDelay))
	{
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUIREDTIMEDELAYNOTEXPIRED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_NOT_OK;
	}
	if(Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]
	 >= Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex].DcmDspSecurityNumAttDelay)
	{
		SchM_Enter_Dcm(Dcm_SecCtrl);
		Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecCurTimer[SecCfgIndex]     = Frt_ReadOutMS();
		Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecExpiredTimer[SecCfgIndex] =
		 (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityDelayTime;
		Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecTimerState[SecCfgIndex]   = DCM_SECTIMER_ON;
		SchM_Exit_Dcm(Dcm_SecCtrl);

		DslInternal_SetSecurityAccessStatus(DCM_SERVICE_IDLE);
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_EXCEEDEDNUMBEROFATTEMPTS);/*NRC=0x36*/
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_NOT_OK;
	}
	/*************************************************/
	/*************************************************/
	/*check whether the corresponding callouts are configured*/
	if ((USE_ASYNCH_FNC == (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityUsePort)
	    || (USE_ASYNCH_CLIENT_SERVER == (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityUsePort))
	{
		ComparedKey = (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].Dcm_CompareKeyFnc;
		GottSeed    = (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].Dcm_GetSeedFnc;
	}

	if ((NULL_PTR == ComparedKey) || (NULL_PTR == GottSeed))
	{
		/*if not configured,send NRC 0x22*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return  E_NOT_OK;
	}
	/*************************************************/
	/*check the request message length*/
	AdrSize  = (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityADRSize;
	SeedSize = (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecuritySeedSize;
	KeySize  = (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityKeySize;
	ReqLen = (uint8)(Dcm_MsgCtrl[MsgCtrlID].MsgContext.ReqDataLen);

	ret = Dcm_Uds0x27ServiceMsgLenCheck(OpStatus,
	                                    ProtocolCtrlId,
		                       			SubFunction,
		                       			ReqLen,
		                       			AdrSize,
		                       			KeySize,
		                       			SecCfgIndex);
	if(E_OK != ret)
	{
		return ret;
	}

	/*************************************************/
	/*get Tx buffer*/
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlID].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

	/*deal with 'request seed'*/
	if (0x01u == (SubFunction & 0x01u))
	{
		/*check whether the Continuous request*/
		if ((SubFunction == Dcm_SecCtrl.Dcm_SubfunctionForSeed) && (Dcm_SecCtrl.Dcm_SecServiceState == DCM_SERVICE_SEED))
		{
			/*to avoid requirement consecutive seed request,same seed is returned.there to clear ServiceState*/
			Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex] += (uint8)1;
			pSecurityRow = &(Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow[SecCfgIndex]);
            if (pSecurityRow != NULL_PTR)
            {
                /*SWS_Dcm_01157*/
                if ((TRUE == pSecurityRow->DcmDspSecurityAttemptCounterEnabled)
                   &&((USE_ASYNCH_FNC == pSecurityRow->DcmDspSecurityUsePort)
                           || (USE_ASYNCH_CLIENT_SERVER == pSecurityRow->DcmDspSecurityUsePort)))
                {
                    if (pSecurityRow->Dcm_SetSecurityAttemptCounterFnc != NULL_PTR)
                    {
                        /*SWS_Dcm_01154*/
                        ret = pSecurityRow->Dcm_SetSecurityAttemptCounterFnc(OpStatus,
                                Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]);
                        if (DCM_E_PENDING == ret)
                        {
                            /*idle*/
                        }
                    }
                }
                if(Dcm_SecCtrl.Dcm_FalseAcessCount[SecCfgIndex]
                                     >= pSecurityRow->DcmDspSecurityNumAttDelay)
                {
                    Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecCurTimer[SecCfgIndex]     = Frt_ReadOutMS();
                    Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecExpiredTimer[SecCfgIndex] =
                    (Dcm_DspCfg.pDcm_DspSecurity->pDcm_DspSecurityRow)[SecCfgIndex].DcmDspSecurityDelayTime;
                    Dcm_SecCtrl.Dcm_RunDlyCtrl.Dcm_SecTimerState[SecCfgIndex]   = DCM_SECTIMER_ON;
                    SchM_Exit_Dcm(Dcm_SecCtrl);
                }
            }
		}

		/*check whether the security service state is idle*/
		ret = Dcm_Uds0x27ServiceActiveSecLevelCheck(ProtocolCtrlId,
													MsgCtrlID,
													ReqSecLevel,
													Offset,
													SeedSize,
													SubFunction);
		if(E_OK != ret)
		{
			return ret;
		}
		/*if the server is on the other security level,check the size of security access data record*/
		#if (DCM_SECURITY_ADR_MAXSIZE > 0)
		if(0u == AdrSize)
		{
		#endif
			 if(DCM_SERVICE_IDLE == Dcm_SecCtrl.Dcm_SecServiceState)
			 {
			    ret = (*GottSeed)(
									#if (DCM_SECURITY_ADR_MAXSIZE > 0)
									NULL_PTR,
									#endif
									OpStatus,
									&Dcm_Channel[Offset + 2u],
									ErrorCode);
			    for(Index=0;Index<SeedSize;Index++)
			    {
			    	Last_Seed[Index] = Dcm_Channel[Offset + 2u + (uint16)Index];
			    }
			 }
			 else
			 {
				 for(Index=0;Index<SeedSize;Index++)
				 {
					 Dcm_Channel[Offset + 2u + (uint16)Index] = Last_Seed[Index];
				 }
				 Dcm_SecCtrl.Dcm_SecServiceState = DCM_SERVICE_IDLE;
			 }
		#if (DCM_SECURITY_ADR_MAXSIZE > 0)
		}
		else
		{   /*read-out ADR  from request message*/
			for(Index=0;Index<AdrSize;Index++)
			{
				Dcm_Adr[Index] = (Dcm_MsgCtrl[MsgCtrlID].MsgContext.pReqData)[Index + 2u];
			}
			if(DCM_SERVICE_IDLE == Dcm_SecCtrl.Dcm_SecServiceState)
			{
			    ret = (*GottSeed)(&Dcm_Adr[0],OpStatus,&Dcm_Channel[Offset + 2u], ErrorCode);
			}
		}
		#endif
        /* check tx data length */
        if(((uint16)0x02u + SeedSize) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
        {
            /*Pdu length is bigger than buffer size,ignore the request message */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
		/* send message */
		Dcm_Uds0x27ServiceReqSeedResp(	ProtocolCtrlId,
										MsgCtrlID,
										SubFunction,
										Offset,
										SeedSize,
										ret	);

	} /*ENDOF if(0x01 == (SubFunction & 0x01u))*/
	/*deal with 'send key'*/
	else
	{
		/*check the status*/
		ret = Dcm_Uds0x27ServiceStatusCheck(OpStatus,ProtocolCtrlId, SubFunction,SecCfgIndex);
		if(E_OK != ret)
		{
			return ret;
		}

		/*if 'requestSeed' and 'seedKey' match,compare the key*/
		ret = (*ComparedKey)(&(Dcm_MsgCtrl[MsgCtrlID].MsgContext.pReqData[2]), OpStatus, ErrorCode);
        /* check tx data length */
        if((2u) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
        {
            /*Pdu length is bigger than buffer size,ignore the request message */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
		/* send message*/
		Dcm_Uds0x27ServiceCompareKeyResp(	OpStatus,
		                                    ProtocolCtrlId,
											MsgCtrlID,
											SubFunction,
											Offset,
											ReqSecLevel,
											SecCfgIndex,
											ret);
	}
	return (ret);
#endif
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif
